<?php

namespace ltcms;
use PhpOffice\PhpWord\Exception\Exception;

/**
 * 应用
 */
class App
{
    /**
     * 实例对象
     * @var
     */
    private static $_instance;

    /**
     * 初始化
     * @var bool
     */
    protected $initialized = false;

    /**
     * 应用开始时间
     * @var float
     */
    protected $beginTime;

    /**
     * 应用内存初始占用
     * @var integer
     */
    protected $beginMem;

    /**
     * 应用根目录
     * @var string
     */
    protected $rootPath = '';

    /**
     * 框架目录
     * @var string
     */
    protected $ltcmsPath = '';

    /**
     * 应用目录
     * @var string
     */
    protected $appPath = '';

    /**
     * Runtime目录
     * @var string
     */
    protected $runtimePath = '';

    /**
     * 路由定义目录
     * @var string
     */
    protected $routePath = '';

    /**
     * 应用调试模式
     * @var bool
     */
    protected $appDebug = true;

    /**
     * 环境变量标识
     * @var string
     */
    protected $envName="";

    /**
     * 应用名称
     * @var string
     */
    protected $appName="";

    /**
     * 初始化
     * App constructor.
     * @param string $rootPath
     */
    private function __construct(){}
    private function __clone(){ }

    /**
     * 初始化
     */
    public function init()
    {
        if(!$this->initialized()){
            $this->ltcmsPath   = realpath(__DIR__) ."/";
            $this->rootPath    = $this->getDefaultRootPath();
            $this->appPath     = $this->rootPath . 'app/';
            $this->runtimePath = $this->rootPath . 'runtime/';
            $this->routePath = $this->rootPath . 'route/';

            //绑定系统容器

            //初始化应用
            try{
                $this->initialize();
            }catch (\Throwable $e){
                throw  $e;
            }
        }
        return $this;
    }

    /**
     * 设置环境变量标识
     * @access public
     * @param string $name 环境标识
     * @return $this
     */
    public function setEnvName($name)
    {
        $this->envName = $name;
        return $this;
    }

    /**
     * 设置应用名称
     * @access public
     * @param string $name 环境标识
     * @return $this
     */
    public function setAppName($name)
    {
        $this->appName = $name;
        return $this;
    }

    /**
     * 是否初始化过
     * @return bool
     */
    public function initialized()
    {
        return $this->initialized;
    }

    /**
     * 初始化应用
     */
    public function initialize(){
        $this->initialized = true;
//        $this->beginTime = microtime(true);
//        $this->beginMem  = memory_get_usage();

        //加载环境文件
        $this->loadEnv($this->envName);

        //设置调试模式
        $this->debugModeInit();

        // 加载全局初始化文件
        $this->load();
    }

    /**
     * 加载环境变量定义
     * @access public
     * @param string $envName 环境标识
     * @return void
     */
    public function loadEnv($envName = '')
    {
        // 加载环境变量
        $envFile = $envName ? $this->rootPath . '.env.' . $envName : $this->rootPath . '.env';
        if (is_file($envFile)) {
            env()->load($envFile);
        }
    }

    /**
     * 加载应用文件和配置
     * @access protected
     * @return void
     */
    protected function load()
    {
        //输入初始化
        request()->initialize();
        //错误处理加载
        error()->register();
        //多应用检测
        multipleApp()->loader($this->appName);
        //初始化语言包
        lang()->loader();
        //配置初始化
        config()->loader();
        //加载常量文件
        $constantsFile=LTCMS_PATH."/lib/Constants.php";
        if(file_exists($constantsFile)){
            @include $constantsFile;
        }
        //设置时区
        date_default_timezone_set(config('app.default_timezone', 'Asia/Shanghai'));
        //设置编码
        header("Content-Type:text/html;charset=".config('app.charset', 'utf-8'));
        //事件注册
        event()->loader();
        //服务注册
        service()->register();
        event()->trigger("appInit");
        //加载路由配置文件
        router()->loader();
        //服务启动
        service()->boot();
    }

    /**
     * 执行应用程序
     */
    public function run()
    {
        try{
            $response = router()->dispatch();
            return $response;
        }catch (\Throwable $e){
            throw  $e;
        }
    }

    /**
     * 获取类对象
     */
    public static  function getInstance(){
        if(!(self::$_instance instanceof self)){
            self::$_instance=new self();
        }
        return self::$_instance;
    }

    /**
     * 调试模式设置
     * @access protected
     * @return void
     */
    protected function debugModeInit()
    {
        // 应用调试模式
        if (!$this->appDebug) {
//            $this->appDebug = $this->env->get('app_debug') ? true : false;
            error_reporting(0);
            ini_set('display_errors', 0);
        }else{
            error_reporting(E_ALL);
            ini_set('display_errors', 1);
        }
    }

    /**
     * 是否运行在命令行下
     * @return bool
     */
    public function runningInConsole()
    {
        return php_sapi_name() === 'cli' || php_sapi_name() === 'phpdbg';
    }

    /**
     * 获取应用根目录
     * @access protected
     * @return string
     */
    protected function getDefaultRootPath()
    {
        return dirname($this->ltcmsPath, 1) . "/";
    }
}